/**
 * 
 */
package com.fdl.dao.base.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;


/**
 * 
 * 实现添、删、改、查等功能 
 * @project: hb-intra
 * @Date:2010-7-29
 * @version  1.0
 * @Company: 33e9
 * @author zhangYong.huang
 */
public abstract class AbstractHibernateDao extends HibernateDaoSupport{

	protected Log logger = LogFactory.getLog(getClass());

	protected Class entityClass;

	protected Class getEntityClass() {
		return entityClass;
	}

	public AbstractHibernateDao(Class entityClass) {
		super();
		this.entityClass = entityClass;
	}
	
	/**
	 * 通过主键查询
	 * @param id
	 * @return
	 */
	public Object load(Serializable id) {
		return (Object) getHibernateTemplate().get(
				getEntityClass(), id);
	}
	
	/**
	 * 获取所有记录
	 * @return
	 */
	public List getAll() {
		return getHibernateTemplate().loadAll(getEntityClass());
	}
	
	/**
	 * 更新或保存
	 * @param entity
	 */
	public void saveOrUpdate(Object entity) {
		Assert.notNull(entity, "entity must be not null!");
		getHibernateTemplate().saveOrUpdate(entity);
	}
	
	/**
	 * 更新或保存
	 * @param entity
	 */
	public void merge(Object entity) {
		Assert.notNull(entity, "entity must be not null!");
		getHibernateTemplate().merge(entity);
	}


	/**
	 * 删除
	 * @param entity
	 */
	public void remove(Object entity) {
		Assert.notNull(entity, "entity must be not null!");
		getHibernateTemplate().delete(entity);
	}

	/**
	 * 执行hsql带条件查询
	 * @param hsql
	 * @param values
	 * @return
	 */
	public List find(String hsql, Object[] values) {
		return getHibernateTemplate().find(hsql, values);
	}

	/**
	 * hsql查询
	 * @param hsql
	 * @return
	 */
	public List find(String hsql) {
		return getHibernateTemplate().find(hsql);
	}

	/**
	 * 执行hsql带条件查询
	 * @param hsql
	 * @param values
	 * @return
	 */
	protected List find(String hsql, Object value) {
		return getHibernateTemplate().find(hsql, value);
	}

	/**
	 * 根据属性名和属性值查询对象.
	 * 
	 * @return 符合条件的唯一对象
	 */
	protected Object findUniqueBy(String name, Object value) {

		Criteria criteria = getEntityCriteria();
		criteria.add(Restrictions.eq(name, value));
		return criteria.uniqueResult();
	}

	/**
	 * 根据属性名和属性值查询对象.
	 * 
	 * @return 符合条件的对象列表
	 */
	public List findBy(String name, Object value) {
		return findBy(name, value, null, null);
	}

	/**
	 * 根据属性名和属性值以Like AnyWhere方式查询对象.
	 */
	protected List findByLike(String name, String value) {
		Criteria criteria = getEntityCriteria();
		criteria.add(Restrictions.like(name, value, MatchMode.ANYWHERE));
		return criteria.list();
	}

	/**
	 * 根据Map中过滤条件进行查询.
	 * 
	 * @param filter
	 *            过滤条件.
	 * @param criteriaSetup
	 *            将Map中条件转换为criteria的call back类
	 */
	protected List findBy(Map filter, CriteriaSetup criteriaSetup) {
		Criteria criteria = getEntityCriteria();
		if (!CollectionUtils.isEmpty(filter)) {
			criteriaSetup.setup(criteria, filter);
		}
		return criteria.list();
	}

	/**
	 * 函数作用同{@link #findBy(Map,CriteriaSetup)} 如果不需要分页,子类可直接重载此函数.
	 */
	protected List findBy(Map filter) {
		return findBy(filter, getDefaultCriteriaSetup());
	}

	protected CriteriaSetup getDefaultCriteriaSetup() {
		return new CriteriaSetup();
	}

	/**
	 * 取得Entity的Criteria.
	 */
	protected Criteria getEntityCriteria() {
		return getSession().createCriteria(getEntityClass());
	}

	protected List findBy(String name, Object value, Map sortMap,
			String cacheRegionName) {
		Criteria criteria = getEntityCriteria();
		criteria.add(Restrictions.eq(name, value));
		if (sortMap != null)
			sortCriteria(criteria, sortMap);
		if (StringUtils.isNotEmpty(cacheRegionName))
			criteria.setCacheable(true).setCacheRegion(cacheRegionName);
		return criteria.list();
	}

	protected List findBy(String name, Object value, Map sortMap) {
		return findBy(name, value, sortMap, null);
	}

	/**
	 * 构造Criteria的排序条件默认函数.可供其他查询函数调用
	 * 
	 * @param criteria
	 *            Criteria实例.
	 * @param sortMap
	 *            排序条件.
	 * @param entity
	 *            entity对象,用于使用反射来获取某些属性信息
	 */
	protected void sortCriteria(Criteria criteria, Map sortMap) {
		if (!sortMap.isEmpty()) {
			Iterator iterator = sortMap.keySet().iterator();
			while (iterator.hasNext()) {
				String fieldName = (String) iterator.next();
				Boolean orderType = (Boolean) sortMap.get(fieldName);

				// 处理嵌套属性如category.name,modify_user.id,暂时只处理一级嵌套
				if (fieldName.indexOf('.') != -1) {
					String alias = StringUtils.substringBefore(fieldName, ".");
					String aliasType = alias;
					// try {
					// aliasType = PropertyUtils.getProperty(entity,
					// alias).getClass().getSimpleName();
					// } catch (Exception e) {
					// logger.error("Get property" + alias + " error");
					// }
					criteria.createAlias(aliasType, alias);
				}

				if (orderType.booleanValue()) {
					criteria.addOrder(Order.asc(fieldName));
				} else {
					criteria.addOrder(Order.desc(fieldName));
				}
			}
		}
	}

	private Object uniqueResult(Collection c) {
		if (c != null && c.size() > 0)
			return c.iterator().next();
		return null;
	}

	protected Object findForObject(String hsql) {
		return uniqueResult(find(hsql));
	}

	protected Object findForObject(String hsql, Object value) {
		return uniqueResult(find(hsql, value));
	}

	protected Object findForObject(String hsql, Object[] values) {
		return uniqueResult(find(hsql, values));
	}
}
